from django import template
from django.http import Http404
from pagemagic.core import get_page_from_path
from pagemagic.models import Page
from pagemagic.utils.goodtext.utils import trunc_text
from django.template.loader import render_to_string

register = template.Library()

@register.inclusion_tag('pagemagic/breadcrumbs.html', takes_context=True)
def show_breadcrumbs(context, last_item_title=None):
    request = context['request']

    if request.pagemagic.currentpage:
        p = request.pagemagic.currentpage
        items = [(p.menu_item.title, None)]
        while p.parent:
            p = p.parent
            if p.path:
                items.insert(0, (p.menu_item.title, p.path))
    elif request.pagemagic.parentpage:
        p = request.pagemagic.parentpage
        items = []
        #while p.parent:
        while p:
            if p.path:
                items.insert(0, (p.menu_item.title, p.path))
            p = p.parent
        if last_item_title:
            items.append((trunc_text(last_item_title, 42, by_spaces=True), None))
    else:
        items = []

#    for item in items:
#        print ' *', item

    return {
        'items': items,
        'request': request,
    }

@register.inclusion_tag('pagemagic/title.html', takes_context=True)
def show_title(context):
    return {'pagemagic': context['request'].pagemagic }


@register.tag
def show_menu(parser, token):
    """
    {% show_menu menu_name as menu_template %}
    or
    {% show_menu menu_name %}
    """
    try:
        tag_name, menu_name, as_, menu_template = token.split_contents() #@UnusedVariable
        if as_ != 'as':
            raise template.TemplateSyntaxError("show_menu tag's invalid syntax")
    except ValueError:
        try:
            tag_name, menu_name = token.split_contents() #@UnusedVariable
            menu_template = '"default_menu.html"'
        except ValueError:
            raise template.TemplateSyntaxError("show_menu tag's invalid syntax")

    return MenuNode(menu_name, menu_template)


@register.tag
def show_menu_branch(parser, token):
    """
    {% show_menu_branch parent as menu_branch_template %}
    or
    {% show_menu_branch parent %}
    """
    try:
        tag, parent, as_, menu_branch_template = token.split_contents() #@UnusedVariable

        if as_ != 'as':
            raise template.TemplateSyntaxError("show_menu_branch tag's invalid syntax")

    except ValueError:
        try:
            tag, parent = token.split_contents() #@UnusedVariable
            menu_branch_template = '"default_menu_branch.html"'
        except ValueError:
            raise template.TemplateSyntaxError("show_menu_branch tag's invalid syntax")

    return MenuBranchNode(parent, menu_branch_template)


def maybevar(s):
    if s[0] == s[-1] == '"':
        return s[1:-1]
    else:
        return template.Variable(s)

def maybe_resolve(maybevar, context):
    try:
        return maybevar.resolve(context)
    except AttributeError:
        return maybevar

class MenuNode(template.Node):
    def __init__(self, path_or_name, menu_template):
        self.path_or_name = maybevar(path_or_name)
        self.menu_template = maybevar(menu_template)
        #print 'self.menu_template', self.menu_template

    def render(self, context):
        request = context['request']
        path_or_name = maybe_resolve(self.path_or_name, context)
        menu_template = maybe_resolve(self.menu_template, context)
        return render_to_string([
            'pagemagic/menus/%s' % menu_template,
            menu_template,
        ], {
            'request': request,
            'root': _get_root(request, path_or_name),
            'menu_template': menu_template,
        }, context)


class MenuBranchNode(template.Node):
    def __init__(self, parent, menu_branch_template):
        self.parent = maybevar(parent)
        self.menu_branch_template = maybevar(menu_branch_template)

    def render(self, context):
        request = context['request']
        menu_branch_template = maybe_resolve(self.menu_branch_template, context)
        parent = maybe_resolve(self.parent, context)

        if isinstance(parent, basestring):
            parent = _get_root(request, parent)

        items = [x for x in request.pagemagic.allpages.by_parent[parent.pk] if x.enabled]
        level = parent.level + 1

        mark_current(request, items)
        return render_to_string([
            'pagemagic/menus/%s' % menu_branch_template,
            menu_branch_template,
        ], {
            'items': items,
            'level': level,
            'request': request,
        }, context)


@register.inclusion_tag('pagemagic/top_level_menu.html', takes_context=True)
def show_top_level_menu(context, path_or_name=None):
    """
    @deprecated: use {% show_menu name template %}
    """
    return _show_menu(context, path_or_name)

@register.inclusion_tag('pagemagic/second_level_menu.html', takes_context=True)
def show_second_level_menu(context, path_or_name=None):
    request = context['request']
    top_root = _get_root(request, path_or_name)

    #menu_root = request.pagemagic.currentpage
    menu_root = request.pagemagic.currentpage or request.pagemagic.parentpage
    while menu_root.parent and menu_root.parent != top_root:
        menu_root = menu_root.parent

    return {
        'root': menu_root,
        'request': request,
        'PAGEMAGIC_PARENTPAGE': context.get('PAGEMAGIC_PARENTPAGE'),
    }

def _show_menu(context, path_or_name=None):
    request = context['request']
    return {
        'root': _get_root(request, path_or_name),
        'request': request,
        'PAGEMAGIC_PARENTPAGE': context.get('PAGEMAGIC_PARENTPAGE'),
    }

def _get_root(request, path_or_name):
    if path_or_name is None:
        return None

    if path_or_name.startswith('/'):
        return get_page_from_path(request, path_or_name)

    try:
        return request.pagemagic.allpages.by_name[path_or_name]
    except KeyError:
        raise Http404('Page `%s` not found' % path_or_name)

def mark_current(request, pages):
    is_curpage_clickable = False
    try:
        curpage = request.pagemagic.currentpage
        nabes = [p.path for p in pages if p.path]
        parentpage = getattr(request, 'PAGEMAGIC_PARENTPAGE', None) or request.pagemagic.parentpage
        if curpage and not curpage.path in nabes:
            if parentpage and parentpage.path != '/':
                is_curpage_clickable = True
    except Http404:
        return

    for p in pages:
        if curpage:
            if (
                p == curpage or
                # hack for setting 2 pages with equals pathes
                p.path.rstrip('#') == curpage.path
            ):
                p.is_current = True
                p.is_clickable = is_curpage_clickable
            elif curpage.has_in_parents(p):
                p.is_clickable = True
                p.is_current = True
        elif parentpage:
            if p == parentpage or parentpage.has_in_parents(p):
                p.is_current = True
                p.is_clickable = True

@register.filter
def startswith(s, path):
    return s.startswith(path)

@register.filter
def pagemagic_urlequal(url, name):
    if name.startswith('/'):
        return url == name
    try:
        return url == pagepath_by_name(name)
    except ValueError:
        return False

@register.simple_tag
def pagemagic_url(name):
    try:
        return pagepath_by_name(name)
    except ValueError:
        return '#unknown-name-for-url--%s' % name

def pagepath_by_name(name, default=None):
    #print '* pagepath_by_name()'
    try:
        return Page.objects.get(name=name).path
    except Page.DoesNotExist:
        if default is None:
            raise ValueError('Cannot get page `%s`' % name)
        else:
            return default
